package com.micro.ai.template.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.micro.ai.commons.exception.BusinessException;
import com.micro.ai.template.client.AuthClient;
import com.micro.ai.template.dto.request.AgentCreateRequest;
import com.micro.ai.template.dto.request.AgentUpdateRequest;
import com.micro.ai.template.dto.response.AgentDTO;
import com.micro.ai.template.entity.AgentInstance;
import com.micro.ai.template.entity.Template;
import com.micro.ai.template.mapper.AgentInstanceMapper;
import com.micro.ai.template.mapper.TemplateMapper;
import com.micro.ai.template.service.AgentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service
public class AgentServiceImpl implements AgentService {

    @Autowired
    private AgentInstanceMapper agentInstanceMapper;

    @Autowired
    private TemplateMapper templateMapper;

    @Autowired
    private AuthClient authClient;

    @Override
    @Transactional
    public AgentDTO createAgent(String userId, String tenantId, AgentCreateRequest request) {
        try {
            // 1. 验证模板是否存在
            Template template = templateMapper.selectOne(
                new LambdaQueryWrapper<Template>()
                    .eq(Template::getTemplateId, request.getTemplateId())
                    .eq(Template::getEnabled, true)
                    .isNull(Template::getDeletedAt)
            );
            
            if (template == null) {
                throw new BusinessException("A0001", "模板不存在或未启用");
            }

            // 2. 创建Agent实体
            AgentInstance agent = new AgentInstance();
            agent.setId(UUID.randomUUID().toString().replace("-", ""));
            agent.setAgentId("agent_" + System.currentTimeMillis());
            agent.setAgentName(request.getAgentName());
            agent.setTemplateId(request.getTemplateId());
            agent.setTemplateVersion(request.getTemplateVersion());
            agent.setDescription(request.getDescription());
            agent.setConfig(request.getConfig());
            
            // 设置租户和用户
            agent.setTenantId(tenantId);
            agent.setCreatedBy(userId);
            
            agent.setStatus("ACTIVE");
            agent.setHealthStatus("UNKNOWN");
            agent.setTags(request.getTags());
            agent.setCreatedAt(LocalDateTime.now());
            agent.setUpdatedAt(LocalDateTime.now());

            // 3. 保存
            agentInstanceMapper.insert(agent);

            // 4. 更新模板使用次数
            template.setUseCount(template.getUseCount() + 1);
            templateMapper.updateById(template);

            // 5. 记录审计日志
            recordAuditLog(userId, tenantId, "agent:create", agent.getAgentId(), 
                          "创建Agent: " + agent.getAgentName());

            return convertToDTO(agent);

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("创建Agent失败", e);
            throw new BusinessException("A0100", "创建Agent失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public AgentDTO updateAgent(String userId, String tenantId, String agentId, AgentUpdateRequest request) {
        try {
            AgentInstance agent = agentInstanceMapper.selectOne(
                new LambdaQueryWrapper<AgentInstance>()
                    .eq(AgentInstance::getAgentId, agentId)
                    .eq(AgentInstance::getTenantId, tenantId)
            );
            
            if (agent == null) {
                throw new BusinessException("A0002", "Agent不存在");
            }

            if (!agent.getCreatedBy().equals(userId)) {
                throw new BusinessException("A0003", "无权修改此Agent");
            }

            if (StringUtils.hasText(request.getAgentName())) {
                agent.setAgentName(request.getAgentName());
            }
            if (StringUtils.hasText(request.getDescription())) {
                agent.setDescription(request.getDescription());
            }
            if (request.getConfig() != null) {
                agent.setConfig(request.getConfig());
            }
            if (StringUtils.hasText(request.getStatus())) {
                agent.setStatus(request.getStatus());
            }
            if (request.getTags() != null) {
                agent.setTags(request.getTags());
            }
            
            agent.setUpdatedAt(LocalDateTime.now());
            agentInstanceMapper.updateById(agent);

            recordAuditLog(userId, tenantId, "agent:update", agentId, "更新Agent: " + agent.getAgentName());

            return convertToDTO(agent);

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新Agent失败", e);
            throw new BusinessException("A0101", "更新Agent失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public void deleteAgent(String userId, String tenantId, String agentId) {
        AgentInstance agent = agentInstanceMapper.selectOne(
            new LambdaQueryWrapper<AgentInstance>()
                .eq(AgentInstance::getAgentId, agentId)
                .eq(AgentInstance::getTenantId, tenantId)
        );
        
        if (agent == null) {
            throw new BusinessException("A0002", "Agent不存在");
        }

        if (!agent.getCreatedBy().equals(userId)) {
            throw new BusinessException("A0003", "无权删除此Agent");
        }

        agent.setStatus("DELETED");
        agent.setDeletedAt(LocalDateTime.now());
        agentInstanceMapper.updateById(agent);

        recordAuditLog(userId, tenantId, "agent:delete", agentId, "删除Agent: " + agent.getAgentName());
    }

    @Override
    public AgentDTO getAgentById(String agentId) {
        AgentInstance agent = agentInstanceMapper.selectOne(
            new LambdaQueryWrapper<AgentInstance>()
                .eq(AgentInstance::getAgentId, agentId)
                .ne(AgentInstance::getStatus, "DELETED")
        );
        
        if (agent == null) {
            throw new BusinessException("A0002", "Agent不存在");
        }

        return convertToDTO(agent);
    }

    @Override
    public Page<AgentDTO> listAgents(String tenantId, Integer pageNum, Integer pageSize, String status) {
        LambdaQueryWrapper<AgentInstance> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AgentInstance::getTenantId, tenantId)
               .ne(AgentInstance::getStatus, "DELETED");
        
        if (StringUtils.hasText(status)) {
            wrapper.eq(AgentInstance::getStatus, status);
        }
        
        wrapper.orderByDesc(AgentInstance::getCreatedAt);

        Page<AgentInstance> page = agentInstanceMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
        return convertPageToDTO(page);
    }

    @Override
    public Page<AgentDTO> getMyAgents(String userId, String tenantId, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<AgentInstance> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AgentInstance::getTenantId, tenantId)
               .eq(AgentInstance::getCreatedBy, userId)
               .ne(AgentInstance::getStatus, "DELETED")
               .orderByDesc(AgentInstance::getCreatedAt);

        Page<AgentInstance> page = agentInstanceMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
        return convertPageToDTO(page);
    }

    @Override
    @Transactional
    public void healthCheck(String agentId) {
        AgentInstance agent = agentInstanceMapper.selectOne(
            new LambdaQueryWrapper<AgentInstance>()
                .eq(AgentInstance::getAgentId, agentId)
        );
        
        if (agent == null) {
            throw new BusinessException("A0002", "Agent不存在");
        }

        // TODO: 实际的健康检查逻辑
        agent.setHealthStatus("HEALTHY");
        agent.setLastHealthCheck(LocalDateTime.now());
        agentInstanceMapper.updateById(agent);
    }

    private void recordAuditLog(String userId, String tenantId, String action, 
                               String resourceId, String description) {
        try {
            Map<String, Object> auditLog = new HashMap<>();
            auditLog.put("userId", userId);
            auditLog.put("tenantId", tenantId);
            auditLog.put("action", action);
            auditLog.put("module", "AGENT");
            auditLog.put("resourceType", "agent");
            auditLog.put("resourceId", resourceId);
            auditLog.put("description", description);
            
            authClient.createAuditLog(auditLog);
        } catch (Exception e) {
            log.warn("记录审计日志失败: {}", e.getMessage());
        }
    }

    private AgentDTO convertToDTO(AgentInstance agent) {
        AgentDTO dto = new AgentDTO();
        BeanUtils.copyProperties(agent, dto);
        
        // 可以通过Feign获取模板名称和用户名
        if (StringUtils.hasText(agent.getTemplateId())) {
            Template template = templateMapper.selectOne(
                new LambdaQueryWrapper<Template>()
                    .eq(Template::getTemplateId, agent.getTemplateId())
            );
            if (template != null) {
                dto.setTemplateName(template.getTemplateName());
            }
        }
        
        return dto;
    }

    private Page<AgentDTO> convertPageToDTO(Page<AgentInstance> page) {
        Page<AgentDTO> dtoPage = new Page<>();
        BeanUtils.copyProperties(page, dtoPage, "records");
        dtoPage.setRecords(page.getRecords().stream()
                .map(this::convertToDTO)
                .toList());
        return dtoPage;
    }
}

